﻿using codeparser.net.v2.Aspects;
using codeparser.net.v2.Entities;
using codeparser.net.v2.Exceptions;

using System;
using System.Globalization;

namespace codeparser.net.v2.Validators
{
    /// <summary>
    /// Represents a token validator that acts case sensitive.
    /// </summary>
    internal class TokenValidatorCaseSensitiveStrategy : TokenValidatorStrategyBase
    {
        /// <summary>
        /// Validates the specified element token.
        /// </summary>
        /// <param name="token">The element token.</param>
        /// <param name="tagConfiguration">The tag configuration.</param>
        /// <returns>The tag.</returns>
        [LoggingAspect]
        internal override Tag ValidateElement(Token token, TagConfiguration tagConfiguration)
        {
            // Validates the element.
            if (!tagConfiguration.Tags.ContainsKey(token.Value.TrimStart('/')))
            {
                throw new InvalidTagException(String.Format(CultureInfo.CurrentCulture,
                    "Invalid tag '{0}' detected", token.Value));
            }

            // Return the appropriate tag.
            return tagConfiguration.Tags[token.Value.TrimStart('/')];
        }

        /// <summary>
        /// Validates the specified attribute token.
        /// </summary>
        /// <param name="token">The attribute token.</param>
        /// <param name="tagConfiguration">The tag configuration.</param>
        [LoggingAspect]
        internal override void ValidateAttribute(Token token, TagConfiguration tagConfiguration)
        {
            // Validates the attribute.
            bool isValidToken = false;
            foreach (Tag tag in tagConfiguration.Tags.Values)
            {
                foreach (TagAttribute attribute in tag.Attributes)
                {
                    if (token.Value == attribute.Name)
                    {
                        isValidToken = true;
                        break;
                    }
                }
                if (isValidToken)
                {
                    break;
                }
            }
            if (!isValidToken)
            {
                throw new InvalidAttributeException(String.Format(CultureInfo.CurrentCulture,
                    "Invalid attribute '{0}' detected", token.Value));
            }
        }

        /// <summary>
        /// Validates the specified attribute token.
        /// </summary>
        /// <param name="token">The attribute token.</param>
        /// <param name="tag">The tag.</param>
        /// <param name="attribute">The attribute as out parameter.</param>
        [LoggingAspect]
        internal override void ValidateAttribute(Token token, Tag tag, out TagAttribute attribute)
        {
            // Validates the attribute.
            attribute = null;
            bool isValidToken = false;
            foreach (TagAttribute tagAttribute in tag.Attributes)
            {
                if (token.Value == tagAttribute.Name)
                {
                    attribute = tagAttribute;
                    isValidToken = true;
                    break;
                }
            }
            if (!isValidToken)
            {
                throw new InvalidAttributeException(String.Format(CultureInfo.CurrentCulture,
                    "Invalid attribute '{0}' detected", token.Value));
            }
        }
    }
}